#! -*- coding: utf-8 -*-
"""
@Author: Gump
@Create Time: 20231214
@Info: 实体标准化处理
"""
from datetime import datetime, timedelta
import re

RULE1 = re.compile('^(今天(早上|中午|晚上|傍晚|上午)?|今日|今早|刚刚|刚才)$')
RULE2 = re.compile('^(今年|本年)$')
RULE3 = re.compile('^(昨天(早上|中午|晚上|傍晚|上午)?|昨晚)$')
RULE4 = re.compile('^(上周|上一周|上1周)$')
RULE5 = re.compile('^(以前|从前)$')
RULE6 = re.compile('^(最近|过去|近|前)([0-9]+)个?([天月年周])$')
RULE7 = re.compile('^截[至止]到?([0-9]+)月底?$')
RULE8 = re.compile('^第?([0-9]+)季度$')
RULE9 = re.compile('^(本周|这个?周|这个?星期)$')
RULE10 = re.compile('^(本月|这个?月)$')
RULE11 = re.compile('^(本季度|这个?季度)$')
RULE12 = re.compile('^截[至止]到?([0-9]+)年底?$')
RULE13 = re.compile('^截[至止]到?(今天|这个?月|本月|月底|年底|今年|昨天|今日)$')
RULE14 = re.compile('^月底$')
RULE15 = re.compile('^年底$')
RULE16 = re.compile('^上1?个?月$')
RULE17 = re.compile('^(上个季度|上季度)$')
RULE18 = re.compile('^去年$')
RULE19 = re.compile('^上半年$')
RULE20 = re.compile('^下半年$')
RULE21 = re.compile('^(\d{4})年(\d{1,2})月份?$')
RULE22 = re.compile('^去年(\d+)个?月份?$')
RULE23 = re.compile('^(\d+)月份?$')
RULE24 = re.compile('^近半年$')


STANDARD_FORMAT_WITH_TIME = '%Y-%m-%d %H:%M:%S'
STANDARD_FORMAT_WITHOUT_TIME = '%Y-%m-%d'

DATE_FORMAT = '\d{8}|\d{4}-\d{2}-\d{2}|\d{4}/\d{1,2}/\d{1,2}|\d{4}年\d{1,2}月\d{1,2}日|\d{4}\.\d{1,2}\.\d{1,2}|' \
              '\d{2}\.\d{2}|\d{1,2}/\d{1,2}|\d{1,2}月\d{1,2}日|\d{1,2}-\d{1,2}'
ONLY_MONTH_DAY = re.compile('^\d{1,2}[-/月.]\d{1,2}日?$')
CH2NUMBER = {'一': '1', '二': '2', '三': '3', '四': '4', '五': '5',
             '六': '6', '七': '7', '八': '8', '九': '9', '两': '2'}
DAYS = {'1': 31, '2': 28, '3': 31, '4': 30, '5': 31, '6': 30,
        '7': 31, '8': 31, '9': 30, '10': 31, '11': 30, '12': 31}


def date_trans(text):
    """日期转换成标准格式"""
    start_timestamp, end_timestamp = None, None
    today = datetime.today()
    weekday = today.weekday()
    if re.search(RULE1, text):
        start_timestamp = today
        end_timestamp = today
    elif re.search(RULE2, text):
        start_timestamp = datetime(year=today.year, month=1, day=1)
        end_timestamp = today
    elif re.search(RULE3, text):
        start_timestamp = today - timedelta(days=1)
        end_timestamp = end_timestamp
    elif re.search(RULE4, text):
        start_timestamp = today - timedelta(days=weekday+7)
        end_timestamp = today - timedelta(days=weekday+1)
    elif re.search(RULE5, text):
        end_timestamp = today
    elif re.search(RULE6, text):
        _, number, key = re.findall(RULE6, text)[0]
        if key == '天':
            start_timestamp = today - timedelta(days=int(number))
        elif key == '周':
            start_timestamp = today - timedelta(days=(7 * int(number)))
        elif key == '月':
            month = today.month - int(number)
            year = today.year
            while month <= 0:
                month += 12
                year -= 1
            start_timestamp = datetime(year=year, month=month, day=today.day)
        elif key == '年':
            start_timestamp = datetime(
                year=(today.year - int(number)), month=today.month, day=today.day)
        end_timestamp = today
    elif re.search(RULE7, text):
        number = re.findall(RULE7, text)[0]
        end_timestamp = datetime(year=today.year, month=int(
            number), day=DAYS.get(number, 30))
    elif re.search(RULE8, text):
        number = re.findall(RULE8, text)[0]
        if number == '1':
            start_timestamp = datetime(year=today.year, month=1, day=1)
            end_timestamp = datetime(year=today.year, month=3, day=31)
        elif number == '2':
            start_timestamp = datetime(year=today.year, month=4, day=1)
            end_timestamp = datetime(year=today.year, month=6, day=30)
        elif number == '3':
            start_timestamp = datetime(year=today.year, month=7, day=1)
            end_timestamp = datetime(year=today.year, month=9, day=30)
        elif number == '4':
            start_timestamp = datetime(year=today.year, month=10, day=1)
            end_timestamp = datetime(year=today.year, month=12, day=31)
    elif re.search(RULE9, text):
        start_timestamp = today - timedelta(days=weekday)
        end_timestamp = today
    elif re.search(RULE10, text):
        start_timestamp = datetime(year=today.year, month=today.month, day=1)
        end_timestamp = today
    elif re.search(RULE11, text):
        month = today.month
        text = '第{}季度'.format((month // 4) + 1)
        start_timestamp, end_timestamp = date_trans(text)
    elif re.search(RULE12, text):
        number = re.findall(RULE12, text)[0]
        if len(number) == 2:
            number = '20' + number
        end_timestamp = datetime(year=int(number), month=12, day=31)
    elif re.search(RULE13, text):
        text = re.findall(RULE13, text)[0]
        _, end_timestamp = date_trans(text)
    elif re.search(RULE14, text):
        month = today.month
        start_timestamp = datetime(
            year=today.year, month=month, day=DAYS.get(str(month), 30))
        end_timestamp = start_timestamp
    elif re.search(RULE15, text):
        start_timestamp = datetime(year=today.year, month=12, day=31)
        end_timestamp = datetime(year=today.year, month=12, day=31)
    elif re.search(RULE16, text):
        this_month = today.month
        if this_month == 1:
            month = 12
            year = today.year - 1
        else:
            month = this_month
            year = today.year
        start_timestamp = datetime(year=year, month=month-1, day=1)
        end_timestamp = datetime(
            year=year, month=month-1, day=DAYS.get(str(month-1), 30))
    elif re.search(RULE17, text):
        month = today.month // 4
        # 特殊情况
        if month == 0:
            start_timestamp = datetime(year=today.year-1, month=10, day=1)
            end_timestamp = datetime(year=today.year-1, month=12, day=31)
        else:
            text = '第{}季度'.format(month)
            start_timestamp, end_timestamp = date_trans(text)
    elif re.search(RULE18, text):
        start_timestamp = datetime(year=today.year - 1, month=1, day=1)
        end_timestamp = datetime(year=today.year - 1, month=12, day=31)
    elif re.search(RULE19, text):
        start_timestamp = datetime(year=today.year, month=1, day=1)
        end_timestamp = datetime(year=today.year, month=6, day=30)
    elif re.search(RULE20, text):
        start_timestamp = datetime(year=today.year, month=7, day=1)
        end_timestamp = datetime(year=today.year, month=12, day=31)
    elif re.search(RULE21, text):
        year, month = re.findall(RULE21, text)[0]
        start_timestamp = datetime(year=int(year), month=int(month), day=1)
        end_timestamp = datetime(year=int(year), month=int(
            month), day=DAYS.get(str(month), 31))
    elif re.search(RULE22, text):
        year = today.year - 1
        month = re.findall(RULE22, text)[0]
        start_timestamp = datetime(year=int(year), month=int(month), day=1)
        end_timestamp = datetime(year=int(year), month=int(
            month), day=DAYS.get(str(month), 31))
    elif re.search(RULE23, text):
        month = re.findall(RULE23, text)[0]
        start_timestamp = datetime(year=today.year, month=int(month), day=1)
        end_timestamp = datetime(year=today.year, month=int(
            month), day=DAYS.get(str(month), 31))
    elif re.search(RULE24, text):
        month = today.month
        year = today.year
        if month <= 6:
            month = month + 6
            year -= 1
        start_timestamp = datetime(year=year, month=month, day=today.day)
        end_timestamp = datetime(
            year=today.year, month=today.month, day=today.day)
    return start_timestamp, end_timestamp


def date2timestamp(str_time):
    """日期转为时间戳"""
    str_time = completion_date(str_time)
    if re.search('^\d{4}-\d{1,2}-\d{1,2}$', str_time):
        return datetime.strptime(str_time, '%Y-%m-%d')
    if re.search('^\d{2,4}年\d{1,2}月\d{1,2}日$', str_time):
        return datetime.strptime(str_time, '%Y年%m月%d日')
    if re.search('^\d{4}/\d{1,2}/\d{1,2}$', str_time):
        return datetime.strptime(str_time, '%Y/%m/%d')
    if re.search('^\d{8}$', str_time):
        return datetime.strptime(str_time, '%Y%m%d')
    if re.search('^\d{4}\.\d{1,2}\.\d{1,2}$', str_time):
        return datetime.strptime(str_time, '%Y.%m.%d')
    return None


def span_time(str_time):
    """时间分割"""
    match = re.findall(DATE_FORMAT, str_time)
    if len(match) == 2:
        start_date, end_date = match
        start_date_stamp = date2timestamp(start_date)
        end_date_stamp = date2timestamp(end_date)
        return start_date_stamp, end_date_stamp
    return None, None


def replace_ch(str_time):
    """替换大写为数字"""
    for key, value in CH2NUMBER.items():
        str_time = str_time.replace(key, value)
    return str_time


def completion_date(text):
    """日期补全"""
    today = datetime.today()
    # 只有月份和日
    if re.search(ONLY_MONTH_DAY, text):
        junction = re.sub('[0-9]+', '', text)[0]
        junction = '年' if junction == '月' else junction
        text = str(today.year) + junction + text
    # 20xx年x月x号
    elif re.search('^\d{2,4}年\d{1,2}月\d{1,2}号$', text):
        text = text.replace('号', '日')
    return text


def date_standard(date_desc, mode='datetime'):
    """时间标准化"""
    standard_format = STANDARD_FORMAT_WITHOUT_TIME if mode == 'date' else STANDARD_FORMAT_WITH_TIME
    # 判断是否区间时间
    start_date_stamp, end_date_stamp = span_time(date_desc)
    if start_date_stamp and end_date_stamp:
        start_date_str = start_date_stamp.strftime(standard_format)
        end_date_str = end_date_stamp.strftime(standard_format)
        return start_date_str, end_date_str
    # 是否标准时间
    date_stamp = date2timestamp(date_desc)
    if date_stamp:
        date_str = date_stamp.strftime(standard_format)
        return date_str, date_str
    # 其他格式时间
    date_desc = replace_ch(date_desc)
    start_date_stamp, end_date_stamp = date_trans(date_desc)
    if start_date_stamp and end_date_stamp:
        start_date_str = start_date_stamp.strftime(standard_format)
        end_date_str = end_date_stamp.strftime(standard_format)
        return start_date_str, end_date_str
    elif start_date_stamp:
        start_date_str = start_date_stamp.strftime(standard_format)
        end_date_str = start_date_str
        return start_date_str, end_date_str
    elif end_date_stamp:
        end_date_str = end_date_stamp.strftime(standard_format)
        return None, end_date_str
    return date_desc, date_desc


if __name__ == '__main__':
    test_time = '20240408-20240409'
    print(date_standard(test_time))
